package com.jdd.modules.sdk.sdkcall;

import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jdd.common.api.vo.Result;
import com.jdd.common.constant.CacheConstant;
import com.jdd.common.constant.JddConstant;
import com.jdd.common.util.CacheUtil;
import com.jdd.common.util.LedControlUtils;
import com.jdd.common.util.SnowFlakeUtil;
import com.jdd.modules.parking.entity.ConfigParkInfo;
import com.jdd.modules.parking.entity.ParkArmInfo;
import com.jdd.modules.parking.mapper.ParkArmInfoMapper;
import com.jdd.modules.parking.mapper.ParkCarEnterLogMapper;
import com.jdd.modules.parking.mapper.ParkCarOutLogMapper;
import com.jdd.modules.parking.service.IConfigParkInfoService;
import com.jdd.modules.parking.service.IParkArmInfoService;
import com.jdd.modules.sdk.SdkCallInterface;
import com.jdd.modules.sdk.config.CameraSdk;
import com.jdd.modules.sdk.sdkidentifycallbackresults.HuaXiaSdkIdentifyCallbackResults;
import com.jdd.modules.sdk.utils.CheckSystemUtil;
import com.jdd.modules.sdk.utils.FeiLiDeLedUtils;
import com.jdd.modules.sdk.utils.QianYiLedUtils;
import com.jdd.modules.sdk.utils.QiXieLedUtils;
import com.jdd.modules.sdk.utils.XiaoMingLedUtils;
import com.jdd.modules.sdk.utils.*;
import com.jdd.modules.sdkopengatelog.entity.SdkOpenGateLog;
import com.jdd.modules.sdkopengatelog.service.ISdkOpenGateLogService;
import com.sun.jna.Pointer;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;

/**
 * @author lcy
 * @date 2021/8/13
 */
@Slf4j
@Component
public class HuaXiaSdkCallInterface extends SdkCallInterface {
    @Value("${huaxia.plateno.enable}")
    private int enable;
    @Resource
    private CameraSdk cameraSdk;
    @Resource
    private CacheUtil cacheUtill;
    @Resource
    private ParkArmInfoMapper parkArmInfoMapper;
    @Resource
    private ISdkOpenGateLogService sdkOpenGateLogService;
    @Resource
    private IParkArmInfoService parkArmInfoService;
    @Resource
    @Lazy
    private HuaXiaSdkIdentifyCallbackResults huaXiaSdkIdentifyCallbackResults;
    @Resource
    private IConfigParkInfoService configParkInfoService;
    @Resource
    private ParkCarEnterLogMapper parkCarEnterLogMapper;
    @Resource
    private ParkCarOutLogMapper parkCarOutLogMapper;
    @Override
    public Result SdkUnfold(String serialNo) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            Pointer handle = cacheUtill.getPointer(CacheConstant.SDK_HANDLE, serialNo);
            if (ObjectUtil.isNull(handle)) {
                return Result.error("请对设备进行初始化");
            }
            //开闸操作
            int i = cameraSdk.getHuaxiasdk().ICE_IPCSDK_OpenGate(handle);
            //开闸操作记录
            LambdaQueryWrapper<ParkArmInfo> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(ParkArmInfo::getSerialNo, serialNo);
            ParkArmInfo parkArmInfo = parkArmInfoMapper.selectOne(queryWrapper);

            SdkOpenGateLog openGateLog = new SdkOpenGateLog();
            BeanUtils.copyProperties(parkArmInfo, openGateLog);
            openGateLog.setCreateTime(new Date());
            openGateLog.setId(SnowFlakeUtil.getId());
            openGateLog.setStateCode(i);
            sdkOpenGateLogService.save(openGateLog);
            if (i != 1) {
                return Result.error("开闸失败");
            }
        } catch (Exception e) {
            log.error("sdk工具类:通过io进行开闸->{}", e);
        }
        return Result.ok().success("开闸成功");
    }

    @Override
    public Result SdkUnfold(String swichType, String serialNo, String plateNo) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            Pointer handle = cacheUtill.getPointer(CacheConstant.SDK_HANDLE, serialNo);
            if (ObjectUtil.isNull(handle)) {
                return Result.error("请对设备进行初始化");
            }
            //开闸操作
            int i = cameraSdk.getHuaxiasdk().ICE_IPCSDK_OpenGate(handle);
            //开闸操作记录
            LambdaQueryWrapper<ParkArmInfo> queryWrapper = new LambdaQueryWrapper();
            queryWrapper.eq(ParkArmInfo::getSerialNo, serialNo);
            ParkArmInfo parkArmInfo = parkArmInfoMapper.selectOne(queryWrapper);
            //出入口id
            String carId;
            //0进口，1出口
            if(JddConstant.StringNumber.STRING_ZERO.equals(parkArmInfo.getArmType())){
                carId = parkCarEnterLogMapper.findIdBySerialAndPlate(serialNo, plateNo);
            }else{
                carId = parkCarOutLogMapper.findIdBySerialAndPlate(serialNo, plateNo);
            }
            SdkOpenGateLog openGateLog = new SdkOpenGateLog();
            BeanUtils.copyProperties(parkArmInfo, openGateLog);
            openGateLog.setId(SnowFlakeUtil.getId());
            openGateLog.setCreateTime(new Date());
            openGateLog.setPlateNo(plateNo);
            openGateLog.setStateCode(i);
            openGateLog.setSwichType(swichType);
            openGateLog.setCapPlace(carId);
            sdkOpenGateLogService.save(openGateLog);

            if (i != 1) {
                return Result.error("开闸失败");
            }
        } catch (Exception e) {
            log.error("sdk工具类:通过io进行开闸->{}", e);
        }
        return Result.ok().success("开闸成功");
    }

    /**
     * @author lcy
     * @date 2021/8/13
     * @Description 华夏初始化分为Windows和Linux两种
     */
    @Override
    public Result CameraSdkInit(String ip) {
        //如果华夏先前已经初始化相机，就不再初始化
        ParkArmInfo parkArmInfoByIp = parkArmInfoService.findParkArmInfoByIp(ip);
        if(null==parkArmInfoByIp){
            return Result.error("查找不到设备信息");
        }
        //连接状态不成功就初始化
        String type = CheckSystemUtil.checkSystem();
        if (type.equals(JddConstant.SystemType.WINDOWS_SYSTEM)) {
            return init(ip);
        }
        return linuxInit(ip);
    }

    /**
     * 设备初始化
     *
     * @author jdd孙庆伟
     * @date 2021/7/28 09:33:48
     */
    public Result init(String ip) {
        try {
            if (StringUtils.isBlank(ip)) {
                return Result.error("设备IP不能为空!");
            }
            log.info("========设备开始进行全局初始化========：ip->{}", ip);
            //初始化
            if (cameraSdk.getHuaxiasdk().ICE_IPCSDK_Init() != 0) {
                log.info("全局设备初始化失败或在先前已经初始化：ip->{}", ip);


                return Result.error("全局设备初始化失败或在先前已经初始化!");
            }
            //连接相机返回句柄
            Pointer handle = cameraSdk.getHuaxiasdk().ICE_IPCSDK_OpenDevice(ip);
            log.info("========获取设备句柄========：handle->{}", handle);
            if (null == handle) {
                log.info("初始化中获取设备句柄失败:{}", handle);
                return Result.error("初始化中获取设备句柄失败!");
            }
            //测试相机连接
            log.info("相机连接状态:{}", cameraSdk.getHuaxiasdk().ICE_IPCSDK_GetStatus(handle));
            if (cameraSdk.getHuaxiasdk().ICE_IPCSDK_GetStatus(handle)) {
                //序列号
                //这里如果使用SDK获取序列号系统会崩溃，情况目前未知
                List<ParkArmInfo> parkArmInfos = parkArmInfoMapper.selectList(new QueryWrapper<ParkArmInfo>().eq("ip_addr", ip));
                String serialNo = parkArmInfos.get(0).getSerialNo();
                //如果链接成功则放入句柄
                cacheUtill.put(CacheConstant.SDK_HANDLE, serialNo, handle);
                //设置UTF-8格式
                cameraSdk.getHuaxiasdk().ICE_IPCSDK_EnableUTF8(handle, enable);
                //设置回调函数
                cameraSdk.getHuaxiasdk().ICE_IPCSDK_SetPlateCallback(handle, huaXiaSdkIdentifyCallbackResults, 0);
            } else {
                return Result.ok("相机连接失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("设备初始化成功:ip->{}", ip);
        return Result.ok("初始化成功");
    }

    /**
     * linux初始化
     *
     * @author jdd孙庆伟
     * @date 2021/8/4 16:28:13
     */
    public Result linuxInit(String ip) {
        try {
            if (StringUtils.isBlank(ip)) {
                return Result.error("设备IP不能为空!");
            }
            log.info("========设备开始进行全局初始化========：ip->{}", ip);
            //连接相机返回句柄
            Pointer handle = cameraSdk.getHuaxiasdk().ICE_IPCSDK_Open(ip, huaXiaSdkIdentifyCallbackResults, 0);
            log.info("========获取设备句柄========：handle->{}", handle);
            if (null == handle) {
                log.info("初始化中获取设备句柄失败:{}", handle);
                return Result.error("初始化中获取设备句柄失败!");
            }
            //测试相机连接
            log.info("相机连接状态:{}", cameraSdk.getHuaxiasdk().ICE_IPCSDK_GetStatus(handle));
            if (cameraSdk.getHuaxiasdk().ICE_IPCSDK_GetStatus(handle)) {
                //序列号
                LambdaQueryWrapper<ParkArmInfo> queryWrapper = new LambdaQueryWrapper<>();
                queryWrapper.eq(ParkArmInfo::getIpAddr, ip);
                ParkArmInfo parkArmInfo = parkArmInfoMapper.selectOne(queryWrapper);
                String serialNo = parkArmInfo.getSerialNo();
                //如果链接成功则放入句柄
                cacheUtill.put(CacheConstant.SDK_HANDLE, serialNo, handle);
            } else {
                return Result.ok("相机连接失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("设备初始化成功:ip->{}", ip);
        return Result.ok("初始化成功");
    }

    @Override
    public Result Sdk485VoiceCommunication(String serialNo, String str) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            Pointer handle = cacheUtill.getPointer(CacheConstant.SDK_HANDLE, serialNo);
            if (ObjectUtil.isNull(handle)) {
                return Result.error("请对设备进行初始化");
            }
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledPlayVoice(str.trim());
            }
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.sdKUnkledSpeech(str.trim());
            }
            if (JddConstant.CameraControl.CONTROLPANEL_QIANYI.equals(configParkInfo.getControlPanelType())) {
                data = QianYiLedUtils.sdKUnkledSpeech(str.trim());
            }
            if (JddConstant.CameraControl.CONTROLPANEL_XIAOMING.equals(configParkInfo.getControlPanelType())) {
                data = XiaoMingLedUtils.ledPlayVoice(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_QIXIE.equals(configParkInfo.getControlPanelType())){
                data= QiXieLedUtils.sdKUnkledSpeech(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_SMALL_FANGKONG.equals(configParkInfo.getControlPanelType())){
                data= SmallFangKongLedUtils.ledPlayVoice(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_YANGZHONGLAI_GREEN.equals(configParkInfo.getControlPanelType())){
                data= YangZhongLaiGreenLedUtils.sdKUnkledSpeech(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_YANGZHONGLAI_BLUE.equals(configParkInfo.getControlPanelType())){
                data= YangZhongLaiBlueLedUtils.sdKUnkledSpeech(str.trim());
            }
            if(JddConstant.CameraControl.CONTROLPANEL_ANKUAI.equals(configParkInfo.getControlPanelType())){
                data= AnKuaiLedUtils.sdKUnkledSpeech(str.trim());
            }
            int ret = cameraSdk.getHuaxiasdk().ICE_IPCSDK_TransSerialPort(handle, data, data.length);
            if (ret != 1) {
                return Result.error("播放失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送语音播报方法—>{}", e);
        }
        return Result.ok().success("成功");
    }

    @Override
    public Result Sdk485TestContentCommunication(String serialNo, String str, String like) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空!");
            }
            Pointer handle = cacheUtill.getPointer(CacheConstant.SDK_HANDLE, serialNo);
            if (ObjectUtil.isNull(handle)) {
                return Result.error("请对设备进行初始化");
            }
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledScreenShowAgreement(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.ledTemporaryDisplay(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_QIANYI.equals(configParkInfo.getControlPanelType())) {
                data = QianYiLedUtils.ledTemporaryDisplay(str.trim(), like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_QIXIE.equals(configParkInfo.getControlPanelType())){
                data= QiXieLedUtils.ledTemporaryDisplay(str.trim(),like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_XIAOMING.equals(configParkInfo.getControlPanelType())) {
                data = XiaoMingLedUtils.ledTemporaryDisplay(str.trim(),like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_SMALL_FANGKONG.equals(configParkInfo.getControlPanelType())){
                data= SmallFangKongLedUtils.ledScreenShowAgreement(str.trim(),like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_YANGZHONGLAI_GREEN.equals(configParkInfo.getControlPanelType())){
                data= YangZhongLaiGreenLedUtils.ledTemporaryDisplay(str.trim(),like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_YANGZHONGLAI_BLUE.equals(configParkInfo.getControlPanelType())){
                data= YangZhongLaiBlueLedUtils.ledTemporaryDisplay(str.trim(),like);
            }
            if(JddConstant.CameraControl.CONTROLPANEL_ANKUAI.equals(configParkInfo.getControlPanelType())){
                data= AnKuaiLedUtils.ledTemporaryDisplay(str.trim(),like);
            }
            int ret = cameraSdk.getHuaxiasdk().ICE_IPCSDK_TransSerialPort(handle, data, data.length);
            if (ret != 1) {
                return Result.error("发送失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送文字临时播放信息方法—>{}", e);
        }
        return Result.ok().success("成功");
    }

    @Override
    public Result GetIsConnect(String serialNo) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空");
            }
            Pointer handle = cacheUtill.getPointer(CacheConstant.SDK_HANDLE, serialNo);
            if (null == handle) {
                return Result.error("请对设备进行初始化");
            }
            //state 输入获取状态的变量地址，输出内容为 1已连上，0未连上
            boolean ret = cameraSdk.getHuaxiasdk().ICE_IPCSDK_GetStatus(handle);
            if (!ret) {
                return Result.error("设备处于断线状态!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:查询设备在线接口报错->{}", e);
        }
        return Result.ok().success("连接成功");
    }

    /**
     * 软触发
     *
     * @param serialNo
     * @return com.jdd.common.api.vo.Result
     * @author jdd孙庆伟
     * @date 2021/8/30 16:58:49
     * @version 1.0
     */
    @Override
    public Result TriggerExt(String serialNo) {
        try {
            if (StringUtils.isBlank(serialNo)) {
                return Result.error("设备序列号不能为空");
            }
            Pointer handle = cacheUtill.getPointer(CacheConstant.SDK_HANDLE, serialNo);
            if (null == handle) {
                return Result.error("请对设备进行初始化");
            }
            int ret = cameraSdk.getHuaxiasdk().ICE_IPCSDK_TriggerExt(handle);
            if (ret != 1) {
                return Result.error("重新识别失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:软触发接口报错->{}", e);
        }
        return Result.ok().success("重新识别成功");
    }
    /*** 功能描述: 同步菲力德的时间
     * @param serialNo 序列号
     * @Author: lcy
     * @Date: 2022/1/4
     */
    public Result Sdk485Calibration(String serialNo){
        if (org.apache.commons.lang.StringUtils.isBlank(serialNo)) {
            return Result.error("设备序列号不能为空!");
        }
        String handle = cacheUtill.get(CacheConstant.SERIAL_HANDLE, serialNo);
        if (org.apache.commons.lang.StringUtils.isBlank(handle)) {
            return Result.error("请对设备进行初始化");
        }
        try {
            //开启透明通道
            int i = Integer.parseInt(handle);
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.calibrationTime();
            }else{
                log.info("------当前系统控制板不是菲力德,无需同步----");
                return Result.ok("无需同步");
            }
            int ret = cameraSdk.zhenshiSdk.VzLPRClient_SerialSend(i, data, data.length);
            if (ret != 0) {
                return  Result.error("同步失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:同步时间—>{}", e);
        }
        return Result.ok().success("成功");
    }
    /**
     *  空闲状态指令
     *  方控：发送广告指令
     *  菲利德：进行内容存储
     * @param str
     * @return
     * @author renshangyi
     * @date 2022/1/26
     */
    @Override
    public Result Sdk485LedAdvertising(String serialNo, String str, String like) {
        String handle = cacheUtill.get(CacheConstant.SERIAL_HANDLE, serialNo);
        if (org.apache.commons.lang.StringUtils.isBlank(handle)) {
            return Result.error("请对设备进行初始化");
        }
        //开启透明通道
        int i = Integer.parseInt(handle);
        try {
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledScreenShowPermanent(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_FEILIDE.equals(configParkInfo.getControlPanelType())) {
                data = FeiLiDeLedUtils.ledDownloadText(str.trim(), like);
            }
            if (JddConstant.CameraControl.CONTROLPANEL_SMALL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.ledScreenShowPermanent(str.trim(), like);
            }
            int ret = cameraSdk.zhenshiSdk.VzLPRClient_SerialSend(i, data, data.length);
            if (ret != 0) {
                return Result.error("发送失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送文字临时播放信息方法—>{}", e);
        }
        return Result.ok().success("成功");
    }

    /**
     *  方控：修改日期显示位置
     * @param   serialNo
     * @return
     * @author renshangyi
     * @date 2022/1/26
     */
    @Override
    public Result Sdk485LedModifyDatePosition(String serialNo,String order) {
        String handle = cacheUtill.get(CacheConstant.SERIAL_HANDLE, serialNo);
        if (org.apache.commons.lang.StringUtils.isBlank(handle)) {
            return Result.error("请对设备进行初始化");
        }
        //开启透明通道
        int i = Integer.parseInt(handle);
        try {
            byte[] data = null;
            ConfigParkInfo configParkInfo = getConfigParkInfo();
            if (JddConstant.CameraControl.CONTROLPANEL_FANGKONG.equals(configParkInfo.getControlPanelType())) {
                data = LedControlUtils.hexToByteArray(order);
            }else{
                log.info("------当前系统控制板不是方控,不能修改日期位置----");
                return Result.error("无法修改");
            }
            int ret = cameraSdk.zhenshiSdk.VzLPRClient_SerialSend(i, data, data.length);
            if (ret != 0) {
                return Result.error("发送失败!");
            }
        } catch (Exception e) {
            log.error("sdk工具类:LED屏幕发送文字临时播放信息方法—>{}", e);
        }
        return Result.ok().success("成功");
    }
    /**
     * @author lcy
     * @date 2021/8/13
     * @Description 拿到当前相机
     */
    private ConfigParkInfo getConfigParkInfo() {
        //这里不作null判断，调用的方法做判断
        return configParkInfoService.findConfigParkInfoByParkCode();
    }
}
